Redux 本身處理同步狀態管理,即每個 action 都會立即被 reducer 處理。然而,現實中我們經常需要處理異步操作,比如從伺服器獲取數據或提交表單。為了讓 Redux 支持異步操作,就會採用方法之一的redux-thunk。
@reduxjs/toolkit
本身就帶有redux-thunk,如果是用一般的redux就會需要再去額外安裝
會延用之前的架構喔,dataSlice.js放在modules
import { createSlice } from "@reduxjs/toolkit";
import axios from "axios";
const dataSlice = createSlice({
name: "data",
initialState: {
data: [],
loading: false,
error: null,
},
reducers: {
fetchDataStart: (state) => {
state.loading = true;
},
fetchDataSuccess: (state, action) => {
state.loading = false;
state.data = action.payload;
},
fetchDataFailure: (state, action) => {
state.loading = false;
state.error = action.payload;
},
},
});
export const { fetchDataStart, fetchDataSuccess, fetchDataFailure } = dataSlice.actions;
export default dataSlice.reducer;
// 這是我們的異步 thunk
export const fetchData = () => async (dispatch) => {
try {
dispatch(fetchDataStart());
const response = await axios.get("https://jsonplaceholder.typicode.com/posts");
dispatch(fetchDataSuccess(response.data));
} catch (error) {
dispatch(fetchDataFailure(error.message));
}
};
npm install axios
axios api需要自行在安裝
createSlice:用於簡化定義 reducers 和 actions 的過程,這裡定義了 dataSlice,包含初始狀態和幾個 reducer 函數。
initialState:這裡定義了三個狀態值:
data: 用於存儲從 API 獲取的數據。
loading: 用於跟蹤數據加載過程中是否還在進行中。
error: 用於存儲異常錯誤信息。
同步 reducer 函數:
fetchDataStart: 請求開始時,將 loading 設置為 true。
fetchDataSuccess: 請求成功後,將 loading 設置為 false,並將獲取的數據存儲到 state.data。
fetchDataFailure: 請求失敗時,將 loading 設置為 false,並將錯誤信息存儲到 state.error。
異步 thunk 函數:
fetchData: 異步請求函數,用 async/await 發送 API 請求,根據結果調用不同的 reducer 更新狀態。
dispatch 的作用是用來發送(dispatch)一個 action 到 Redux store,從而觸發對應的 reducer 函數來更新應用中的狀態。
這邊指的是store裡的,外面的統一用main.js好了
import { configureStore } from "@reduxjs/toolkit";
import dataReducer from "./modules/dataSlice";
const store = configureStore({
reducer: {
data: dataReducer,
},
});
export default store;
同之前的配置並無甚麼特殊變化,不過其實他有多一個回調函數middleware,因為 @reduxjs/toolkit 已經自動配置了 redux-thunk。只有在需要添加或自定義其他中間件時,才需要顯式寫 middleware。
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchData } from './store/modules/dataSlice';
const DataComponent = () => {
const dispatch = useDispatch();
const { data, loading, error } = useSelector((state) => state.data);
useEffect(() => {
dispatch(fetchData()); // 組件加載時發送請求
}, [dispatch]);
if (loading) {
return <p>Loading...</p>;
}
if (error) {
return <p>Error: {error}</p>;
}
return (
<div>
<h1>Data from API</h1>
<ul>
{data.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
</div>
);
};
export default DataComponent;
執行 dispatch(fetchData()) 時,它表示你想要發送 fetchData 這個異步函數(thunk)作為 action。
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';
ReactDOM.createRoot(document.getElementById('root')).render(
<Provider store={store}>
<App />
</Provider>
);
這沒什麼變動就不多做說明了
今天就這樣囉,異步操作主要還是api之類的會很需要,再來redux本身是專門處理同步的如果沒有react-thunk就無法使用。